package com.lemon.boot.common.handler;

import com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties;
import com.lemon.boot.common.annotation.ResponseNotResult;
import com.lemon.boot.common.properties.JwtConfigProperties;
import com.lemon.boot.common.web.Result;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author 李猛
 * @datetime 2024/4/12 17:35
 * @description 类对象
 */
@Slf4j
@Getter
@Setter
@ControllerAdvice
@ConfigurationProperties(prefix = "response")
@AutoConfigureAfter(JwtConfigProperties.class)
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
    private List<String> success;

    public List<String> passUriList;

    public ResponseResultHandler(JwtConfigProperties properties) {
        this.passUriList = properties.getAllPassUriByList();
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return (returnType.getParameterType() != Result.class && !returnType.hasMethodAnnotation(ResponseNotResult.class));
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        log.info("returnType:{}", returnType.getParameterType());

        //1.判断请求路径是否是 Knife4j 的请求路径
        final String path = request.getURI().getPath();
        boolean match = passUriList.stream().anyMatch(item -> (item.endsWith("/**") && path.startsWith(item.substring(0, item.length() - 2))) || path.equals(item));
        if (match) {
            return body;
        }

        //2.如果返回的 String 对象，需要判断返回的字符串里有没有 规定的关键字
        boolean matchStr = returnType.getParameterType() == String.class && body != null && success.stream().noneMatch(item -> Objects.toString(body).contains(item));
        if (matchStr) {
            return Result.fail(Objects.toString(body));
        } else {
            return Result.ok(body);
        }
    }
}
